#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

class String {
public:
    String();
    //explicit
    String(const char* pstr);
    String(const String& rhs);
    ~String();
    String& operator=(const String& rhs);
    String& operator=(const char* pstr);

    String& operator+=(const String& rhs);
    String& operator+=(const char* pstr);

    char& operator[](std::size_t index);
    const char& operator[](std::size_t index) const;

    std::size_t size() const;
    const char* c_str() const;

    friend bool operator==(const String& lhs, const String& rhs);
    friend bool operator!=(const String& lhs, const String& rhs);

    friend bool operator<(const String& lhs, const String& rhs);
    friend bool operator>(const String& lhs, const String& rhs);
    friend bool operator<=(const String& lhs, const String& rhs);
    friend bool operator>=(const String& lhs, const String& rhs);

    friend std::ostream& operator<<(std::ostream& os, const String& s);
    friend std::istream& operator>>(std::istream& is, String& s);

    friend String operator+(const String& lhs, const String& rhs);
    friend String operator+(const String& lhs, const char* pstr);
    friend String operator+(const char* pstr, const String& rhs);
private:
    char* _pstr;
};


// 无参构造：创建一个空字符串
String::String() : _pstr(new char[1]()) {}

// C风格字符串构造
String::String(const char* pstr) 
    : _pstr(new char[strlen(pstr) + 1]())
{
    strcpy(_pstr, pstr);
    cout << "有参构造，接受一个C风格字符串" << endl;
}

// 拷贝构造
String::String(const String& rhs)
    : _pstr(new char[strlen(rhs._pstr) + 1])
{
    strcpy(_pstr, rhs._pstr);
    cout << "拷贝构造" << endl;
}

// 析构函数
String::~String() {
    if (_pstr) {
        delete [] _pstr;
        _pstr = nullptr;
    }
}

// 赋值运算符 String
// 四步走
String& String::operator=(const String& rhs) {
    if (this != &rhs) { // 1. 避免自复制问题
        delete [] _pstr; // 2. 回收原来的空间
        _pstr = new char[strlen(rhs._pstr) + 1](); // 3. 申请新空间 深拷贝
        strcpy(_pstr, rhs._pstr);
    }
    return *this; // 4
}

// 赋值运算符 C风格字符串
String& String::operator=(const char* pstr) {
    delete [] _pstr;
    _pstr = new char[strlen(pstr) + 1]();
    strcpy(_pstr, pstr);
    cout << "operator= 接受一个C风格字符串" << endl;
    return *this;
}

// 重载+= String
String& String::operator+=(const String& rhs) {
    // 获取拼接后的总长度
    int len = strlen(_pstr) + strlen(rhs._pstr) + 1;
    // 申请新空间
    char* res = new char[len]();
    // 拼接
    strcat(res, _pstr);
    strcat(res, rhs._pstr);
    // 回收原来的空间
    delete [] _pstr;
    _pstr = res;
    
    return *this;
}

// 重载+= C风格字符串
String& String::operator+=(const char* pstr) {
    // 获取拼接后的总长度
    int len = strlen(_pstr) + strlen(pstr) + 1;
    // 申请新空间
    char* res = new char[len]();
    // 拼接
    strcat(res, _pstr);
    strcat(res, pstr);
    // 回收原来的空间
    delete [] _pstr;
    _pstr = res;

    return *this;
}

char& String::operator[](std::size_t index) {
    if (index < strlen(_pstr)) {
        return _pstr[index]; 
    }
    else {
        cout << "index is invalid!" << endl;
        static char nullchar = '\0';
        return nullchar;
    }
}

const char& String::operator[](std::size_t index) const {
    if (index < strlen(_pstr)) {
        return _pstr[index]; 
    }
    else {
        cout << "index is invalid!" << endl;
        static char nullchar = '\0';
        return nullchar;
    }
}

std::size_t String::size() const {
    return strlen(_pstr);
}


const char* String::c_str() const {
    return _pstr;
}

bool operator==(const String& lhs, const String& rhs) {
    // strcmp判断如果相等的话返回的是0，所以要取反
    return !strcmp(lhs._pstr, rhs._pstr);
}

bool operator!=(const String& lhs, const String& rhs) {
    return strcmp(lhs._pstr, rhs._pstr);
}

bool operator<(const String& lhs, const String& rhs) {
    if (strcmp(lhs._pstr, rhs._pstr) < 0) {
        return true;
    }
    return false;
}

bool operator>(const String& lhs, const String& rhs) {
    if (strcmp(lhs._pstr, rhs._pstr) > 0) {
        return true;
    }
    return false;
}

bool operator<=(const String& lhs, const String& rhs) {
    if (strcmp(lhs._pstr, rhs._pstr) <= 0) {
        return true;
    }
    return false;
}

bool operator>=(const String& lhs, const String& rhs) {
    if (strcmp(lhs._pstr, rhs._pstr) >= 0) {
        return true;
    }
    return false;
}

std::ostream& operator<<(std::ostream& os, const String& s) {
    os << s._pstr;
    return os;
}

std::istream& operator>>(std::istream& is, String& s) {
    char temp[1024] = { 0 };
    is >> temp;
    
    if (s._pstr) {
        delete [] s._pstr;
    }
    temp[strlen(temp)] = '\0';
    s._pstr = new char[strlen(temp) + 1]();
    strcpy(s._pstr, temp);
    return is;
}


// 重载String + String
String operator+(const String &lhs,const String& rhs) {
    // 获取拼接后的总长度
    int len = strlen(lhs._pstr) + strlen(rhs._pstr) + 1;
    // 申请新空间
    char* res = new char[len]();
    // 拼接
    strcat(res, lhs._pstr);
    strcat(res, rhs._pstr);
    // 回收原来的空间
    String tmp;
    delete [] tmp._pstr;
    tmp._pstr = res;
    return tmp;
}
void test0(){
    String str("hello");
    //本质是隐式转换，底层逻辑：使用一个C风格字符串去创建一个
    //临时的String对象，再使用拷贝构造将临时对象的内容复制给str2
    //表层上，将其视为构造函数的调用
    String str2 = "world";
    str2 = "hello";

    /* int num = 10; */
    /* int num2(20); */
}

int main(void){
    test0();
    return 0;
}

